<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>非父子组件间通信</title>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>
<body>

<div id="communication1">
    {{ message }}
    <cus-com></cus-com>
</div>

<div id="parent_demo">
    <!-- 子组件中使用this.$parent可以直接访问该组件的父组件 -->
    {{ message }}
    <parent-demo-custom-com></parent-demo-custom-com>
</div>
<div id="children_demo">
    <h5>子组件索引</h5>
    <p>vue提供了子组件索引的方法,用特殊的ref来为子组件指定一个索引名称</p>
    <button @click="handleRef">通过ref来获取子组件实例</button>
    <children-demo-com-a ref="comA"></children-demo-com-a>
    {{ msg }}
</div>
<div>
    <h5>7.4 使用solt分发内容</h5>
    <p>pros分发内容,events触发事件,slot内容分发构成了Vue组件的3个数据来源,再复杂的组件也是由这三部分组成的</p>
    <div id="solt_demo">
        <p>演示1</p>
        <children-com-slot-a :show-children="showChildren"></children-com-slot-a>
    </div>

    <div id="solt_demo_a">
        <p>演示2</p>
        <children-com-slot-a :show-children="showChildren"><p>分发的内容</p></children-com-slot-a>
    </div>
    <div id="slot_demo_b">
        <children-com-slot-b>
            <p slot="header"><strong>标题</strong></p>
            <div>
                这是一个div
            </div>
            <div slot="footer">footer</div>
        </children-com-slot-b>
    </div>
    <div id="slot_demo_c">
        <h6>作用域卡槽</h6>

        <children-com-slot-c>
            <template scope="props">
                <p>来自父组件的内容</p>
                <p>{{ props.msg }}</p>
            </template>
        </children-com-slot-c>
        <div>
            <children-com-slot-d :books="books">
                <template slot="book" scope="props">
                    <li>{{ [props.bookName] }}</li>
                </template>

            </children-com-slot-d>
        </div>
    </div>
    <div id="slot_demo_e">
        <h6>7.4.5 访问slot</h6>
        <children-com-slot-e>
            <p slot="header">标题</p>
            <p>正文内容</p>
            <p>使用$slots可以直接访问slot内容</p>
            <div slot="footer">
                底部信息
            </div>
        </children-com-slot-e>
    </div>
</div>
<div id="app_component">
    <h5>7.5 组件高级用法</h5>
    <h6>组件在模板内可以递归的调用自己</h6>
    <div>
        <children-demo-com-f :count="1">

        </children-demo-com-f>
    </div>
    <div>
        <h6>
            7.5.2 内联模板
        </h6>
        <p>
            组件的模板一般都是在template选项内定义的，Vue提供了一个内联模板的功能，
            在使用组件时，给组件标签使用inline-template特性，组件就会把它的内容当作模板，
            而不是把它当内容分发，这让模板更灵活。
        </p>
        <children-demo-com-g inline-template>
            <div>
                <h2>在父组件中定义组件的模板</h2>
                <p>{{ message }}</p>
                <p>{{ msg }}</p>
            </div>
        </children-demo-com-g>
        <p>
            在父组件中声明的数据message和子组件中声明的数据msg，两个都可以渲染（如果同名优先使用子组件的数据）。
        </p>
    </div>
    <div>
        <h6>7.5.3 动态组件</h6>
        <p>Vue提供了一个特殊的元素&lt;component&gt;用来挂载不同的组件，使用is特性来选择要挂载的组件。示例如下</p>
        <div>
            <component :is="currentView"></component>

            <button @click="handleChangeView('A')">切换A</button>
            <button @click="handleChangeView('B')">切换B</button>
            <button @click="handleChangeView('C')">切换C</button>

        </div>
        <p>直接挂载组件</p>
        <div>
            <component :is="home"></component>
        </div>
    </div>
    <div>
        <h6>7.5.4 </h6>
        <p>当工程足够大，使用的组件足够多时，是时候考虑一下性能问题了。因为一开始把所有的组件都加载是没有必要的一笔开销。
            Vue.js 允许组件定义为一个工厂函数，动态地解析组件。Vue.js只在组件需要渲染时触发工厂函数，并且把结果缓存起来，用于后面的再次渲染。
            示例如下
        </p>
        <div>
            <children-demo-com-h></children-demo-com-h>
        </div>
        <p>工厂函数接受一个resolve回调，在收到从服务器下载的组件定义时调用。也可以调用reject(reason)指示加载失败，这里的setTimeOut只是为了演示异步，
            具体的逻辑可以自己决定，比如把组件的配置写成一个对象配置，通过Ajax来请求，然后调用resolve传入配置选项。也可以通过webpack和.vue单文件的方法来实现异步组件（路由）。</p>
    </div>


</div>
<div id="other">
    <h6>7.6 其他</h6>
    <p>$nextTick</p>
    <div id="showDemo" v-if="showDiv">
        这是一段文本
    </div>
    <button @click="getText">获取div的内容</button>
    <p>X-Templates</p>
    <p>手动挂载实例</p>
    <div id="manual"></div>

</div>

<div>
    <h6>7.7 实战：两个常用组件的开发</h6>
</div>


<script src="https://unpkg.com/vue/dist/vue.min.js"></script>
<script>

    //    首先创建一个空的bus空对象,用于发送消息和传递消息
    let bus = new Vue()
    Vue.component('cus-com', {
        template: '<button @click="handleDispatch">派发事件</button>',
        methods: {
            handleDispatch: function () {

                // this.$dispatch('on-message','来自内部组件的数据') Vue1.x写法
                bus.$emit('on-message', '来自内部组件的数据')
            }
        }
    });

    let communication1 = new Vue({
        el: '#communication1',
        data: {
            message: ''
        },
        // events:{
        //     'on-message': function (msg){
        //         this.message = msg
        //     }
        // }
        mounted() {
            let _this = this;

            bus.$on('on-message', function (msg) {
                _this.message = msg
            })
        }

    })

</script>
<script>
    Vue.component('parent-demo-custom-com', {
        template: '<button @click="handleEvent">通过父链直接修改数据</button>',
        methods: {
            handleEvent: function () {
                this.$parent.message = '被子组件修改后的内容'
            }
        }
    })
    new Vue({
        el: '#parent_demo',
        data: {
            message: '原本内容'
        }
    })
</script>
<script>
    Vue.component('children-demo-com-a', {
        template: '<div>子组件</div>',
        data: function () {
            return {
                message: '子组件内容'
            }
        }
    })
    new Vue({
        el: '#children_demo',
        data: {
            msg: 'aaa'
        },
        methods: {
            handleRef: function () {
                console.log(this.msg)
                this.msg = this.$refs.comA.message
                console.log(this.msg)
            }
        }
    })
</script>
<script>
    Vue.component('children-com-slot-a', {
        template: '<div v-show="showChildren">\
        <slot>\
        <p>如果父组件没有插入内容,我将默认出现</p>\
        </slot>\
            </div>',
        props: {
            showChildren: {
                type: Boolean
            }
        }
    })
    new Vue({
        el: '#solt_demo',
        data: {
            showChildren: true
        }
    })
</script>
<script>
    Vue.component('children-com-slot-b', {
        template: '<div class="container">\
            <div class="header"><slot name="header">默认header内容</slot></div>\
            <div class="main"><slot>默认main内容</slot></div>\
            <div class="footer"><slot name="footer"></slot></div>\
            \</div>'
    })
    new Vue({
        el: '#slot_demo_b'
    })
</script>
<script>
    Vue.component('children-com-slot-c', {
        template: '<div class="container">\
        <slot msg="来自子组件的内容"></slot>\
        </div>'
    })

    Vue.component('children-com-slot-d', {
        template: '\
        <ul>\
        <slot name="book" v-for="book in books"\
    :book-name="book.name"></slot>\
            </ul>'
        ,
        props: {
            books: {
                type: Array,
                default: function () {
                    return []
                }
            }
        }
    })
    Vue.component('children-com-slot-e', {
        template: '\
        <div class="container">\
        <div class="header">\
        <slot name="header">dsadsa</slot>\
        </div>\
        <div class="main">\
        <slot></slot>\
        </div>\
        <div class="footer">\
        <slot name="footer"></slot>\
        </div>\
        </div>\
        ',
        mounted: function () {
            let header = this.$slots.header
            let main = this.$slots.main
            let footer = this.$slots.footer
            console.log("dads")
            console.log(footer)
            console.log(footer[0].elm.innerHTML)
        }
    })
    new Vue({
        el: '#slot_demo_c',
        data: {
            books: [{
                name: '《CSS基础》'
            }]
        }
    })
    new Vue({
        el: '#slot_demo_e'
    })

</script>
<script>
    Vue.component('children-demo-com-f', {
        name: 'children-demo-com-f',
        template: '<div class="child">\
         <children-demo-com-f :count="count+1"\
         v-if="count <3 ">\
         </children-demo-com-f></div>',
        props: {
            count: {
                type: Number,
                default: 1
            }
        }

    })
    Vue.component('children-demo-com-g', {
        data: function () {
            return {
                msg: '在子组件中声明数据'
            }
        }
    })

    let Home = {
        template: '<p>演示直接挂载组件</p>'
    }
    new Vue({
        el: '#app_component',
        data: {
            message: '在父组件中声明数据',
            currentView: 'comA',
            home: Home,
            showDiv: false
        },

        methods: {
            handleChangeView: function (component) {
                this.currentView = 'com' + component
            }
        },
        components: {
            comA: {
                template: '<div>A组件</div>'
            },
            comB: {
                template: '<div>B组件</div>'
            },
            comC: {
                template: '<div>C组件</div>'
            },
            childrenDemoComH: function (resolve, reject) {
                window.setTimeout(function () {
                    resolve({
                        template: '<div>我是异步渲染的</div>'
                    })
                }, 2000)
            }
        }
    })
</script>
<script>
    let cusComponent = Vue.extend({
        template: '<div>Hello:{{name}}</div>',
        data: function () {
            return {
                name: 'LIQINCHUN'
            }
        }
    })
    // new cusComponent().$mount('#manual')
    // new cusComponent({
    //     el:'#manual'
    // })
    let component1 = new cusComponent().$mount();

    document.getElementById('manual').appendChild(component1.$el);
    new Vue({
        el: '#other',
        data: {
            showDiv: false
        },
        methods: {
            getText: function () {
                this.showDiv = true;
                //
                // let text = document.getElementById('showDemo').innerText
                this.$nextTick(function () {
                    let text = document.getElementById('showDemo').innerText
                    console.log(text)

                })
            }
        }
    })
</script>
</body>
</html>